package com.xy.smartsms.plugincmcc;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.text.TextUtils;
import com.xy.smartsms.util.Log;
import android.util.LruCache;

import com.xy.smartsms.data.SmsItem;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2017/3/3.
 */

public class CMCCDataCache {
    private static final String TAG = CMCCDataCache.class.getSimpleName();
    private static final int EXPIRE_VALID = 7 * 24 * 3600 * 1000; // 7day
    private static final int EXPIRE_NULL = 5 * 60 * 1000; // 5minute
    public static final String CARRIER_NULL_RESULT = "carrier_null";
    private static CMCCDataCache sInstance = null;
    // only cache data in current conversation, means with same phone number
    private static LruCache<String, String> sLocalCache = new LruCache<String, String>(100);
    private Context mContext = null;
    private CMCCDataDBHelper mDBHelper = null;


    private CMCCDataCache(Context context) {
        this.mContext = context;
        mDBHelper = new CMCCDataDBHelper(context);
    }

    public static CMCCDataCache getInstance() {
        return sInstance;
    }

    public static synchronized CMCCDataCache getInstance(Context context) {
        if (sInstance == null) {
            sInstance = new CMCCDataCache(context);
        }
        return sInstance;
    }

    private String getCacheKey(SmsItem item) {
        return item.getCacheKey();
    }

    public String queryCacheResult(SmsItem item) {
        String msgId = item.getMsgId();
        String phoneNum = item.getPhone();
        String smsMsg = item.getBody();
        String cacheResult = null;
        if (TextUtils.isEmpty(msgId) || TextUtils.isEmpty(phoneNum) || TextUtils.isEmpty(smsMsg)) {
            return cacheResult;
        }
        String localKey = getCacheKey(item);
        cacheResult = sLocalCache.get(localKey);
        return cacheResult;
    }

    public void clearLruCache() {
        sLocalCache.evictAll();
    }

    private List<String> getCacheKeyList(String msgId) {
        ArrayList<String> resultList = new ArrayList<>();
        Cursor cursor = null;
        SQLiteDatabase database = mDBHelper.getWritableDatabase();
        try {
            cursor = database.query(CMCCDataDBHelper.TABLE_NAME,
                    new String[]{"queryKey"},
                    "msgId = ?",
                    new String[]{msgId},
                    null,
                    null,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                do {
                    resultList.add(cursor.getString(cursor.getColumnIndex("queryKey")));
                } while (cursor.moveToNext());
            }
        } catch (Throwable t) {
            Log.e(TAG, "getCacheKeyList", t);
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }

        return resultList;
    }

    private void deleteKey(List<String> keyList) {
        if (keyList == null || keyList.size() == 0) {
            return;
        }

        SQLiteDatabase database = mDBHelper.getWritableDatabase();
        StringBuilder sb = new StringBuilder();
        sb.append("(");
        for (String k : keyList) {
            // SMARTISAN-766
            sb.append("'" + k + "'" + ",");
        }

        sb.deleteCharAt(sb.length() - 1);
        sb.append(")");
        database.delete(CMCCDataDBHelper.TABLE_NAME, "queryKey in " + sb.toString(), null);
    }

    public synchronized void updateCacheData(SmsItem item, String result, boolean needCache) {
        String msgId = item.getMsgId();
        String phoneNum = item.getPhone();
        String smsMsg = item.getBody();
        if (TextUtils.isEmpty(msgId)
                || TextUtils.isEmpty(phoneNum)
                || TextUtils.isEmpty(smsMsg)
                || TextUtils.isEmpty(result)) {
            return;
        }

        Cursor cursor = null;
        String localKey = getCacheKey(item);
        List<String> keyList = getCacheKeyList(msgId);
        try {
            SQLiteDatabase database = mDBHelper.getWritableDatabase();

            ContentValues newValues = new ContentValues();
            newValues.put("msgId", msgId);
            newValues.put("phoneNum", phoneNum);
            newValues.put("result", result);
            newValues.put("queryKey", localKey);
            newValues.put("parseTime", System.currentTimeMillis());

            String whereClause = "queryKey = ?";
            if (keyList == null || keyList.size() == 0) {
                database.insert(CMCCDataDBHelper.TABLE_NAME,
                        null,
                        newValues);
            } else if (keyList.contains(localKey)) {
                database.update(CMCCDataDBHelper.TABLE_NAME,
                        newValues,
                        whereClause,
                        new String[]{localKey});
                keyList.remove(localKey);
            }

            if (needCache) {
                sLocalCache.put(localKey, result);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        
        deleteKey(keyList);
    }

    public synchronized String queryCacheResultFromDB(SmsItem item) {
        String msgId = item.getMsgId();
        String phoneNum = item.getPhone();
        String smsMsg = item.getBody();
        String cacheResult = null;
        if (TextUtils.isEmpty(msgId) || TextUtils.isEmpty(phoneNum) || TextUtils.isEmpty(smsMsg)) {
            return cacheResult;
        }

        Cursor cursor = null;
        List<String> keyList = new ArrayList<>();
        String cacheKey = getCacheKey(item);
        try {
            SQLiteDatabase database = mDBHelper.getReadableDatabase();
            String whereClause = "queryKey = ?";
            cursor = database.query(CMCCDataDBHelper.TABLE_NAME,
                    new String[]{"result", "parseTime"},
                    whereClause,
                    new String[]{cacheKey},
                    null,
                    null,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                cacheResult = cursor.getString(cursor.getColumnIndex("result"));
                long parseTime = cursor.getLong(cursor.getColumnIndex("parseTime"));
                int expire = cacheResult.equals(CARRIER_NULL_RESULT) ? EXPIRE_NULL : EXPIRE_VALID;
                if (parseTime + expire > System.currentTimeMillis()) {
                    sLocalCache.put(cacheKey, cacheResult);
                } else {
                    sLocalCache.remove(cacheKey);
                    keyList.add(cacheKey);
                    cacheResult = null;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }

        deleteKey(keyList);
        return cacheResult;
    }

    public synchronized void loadCacheResultsFromDB(String phoneNum) {
        Cursor cursor = null;
        List<String> keyList = new ArrayList<>();
        try {
            SQLiteDatabase database = mDBHelper.getReadableDatabase();
            String whereClause = "phoneNum = ?";
            cursor = database.query(CMCCDataDBHelper.TABLE_NAME,
                    new String[]{"result", "queryKey", "parseTime"},
                    whereClause,
                    new String[]{phoneNum},
                    null,
                    null,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                do {
                    long parseTime = cursor.getLong(cursor.getColumnIndex("parseTime"));
                    String cacheResult = cursor.getString(cursor.getColumnIndex("result"));
                    String cacheKey = cursor.getString(cursor.getColumnIndex("queryKey"));
                    int expire = cacheResult.equals(CARRIER_NULL_RESULT) ? EXPIRE_NULL : EXPIRE_VALID;
                    if (parseTime + expire > System.currentTimeMillis()) {
                        sLocalCache.put(cacheKey, cacheResult);
                    } else {
                        sLocalCache.remove(cacheKey);
                        keyList.add(cacheKey);
                    }
                } while (cursor.moveToNext());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        
        deleteKey(keyList);
    }
}
